﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Threading;
using Net.Chirash.Twitter.TweetZone.WindowComponents;
using Net.Chirash.Twitter.TweetZone.WindowComponents.Containers;
using Net.Chirash.Twitter.TwitterClient;
using Net.Chirash.Twitter.TwitterClient.DBSyncronize;
using Net.Chirash.Twitter.TwitterDatabase;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Net.Chirash.Twitter.TweetZone
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Constructors

        public MainWindow()
        {
            InitializeComponent();
            //refreshBackgroundWorker.DoWork += new DoWorkEventHandler(refreshBackgroundWorker_DoWork);
            //refreshBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshBackgroundWorker_RunWorkerCompleted);
            //refreshBackgroundWorker.WorkerSupportsCancellation = true;

            //refreshTimer.Tick += new EventHandler(refreshTimer_Tick);
            //refreshTimer.Interval = TweetZone.Properties.Settings.Default.RefreshInterval;

            UpdateForm.RefreshMainWindow = new UpdateForm.RefreshMainWindowCallback(StartRefresh);
            MainUpdateForm.UpdateButton.Click += new RoutedEventHandler(MainUpdateForm_UpdateButton_Click);
            StatusBox.DirectMessageInMainWindow = new StatusBox.DirectMessageInMainWindowCallback(DirectMessage);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// 初回起動時にOAuthトークンを取得するためのブラウザを呼び出し設定に保存する。次回以降は設定ファイルからトークンを読み込む
        /// </summary>
        private void SetupConnection()
        {
            string token = Properties.Settings.Default.AccessToken;
            string tokenSecret = Properties.Settings.Default.AccessTokenSecret;
            TwitterConnection connection = App.CurrentApp.Connection;
            if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(tokenSecret))
            {
                if (string.IsNullOrEmpty(connection.Token) || string.IsNullOrEmpty(connection.TokenSecret))
                {
                    OAuthBrowser browser = new OAuthBrowser(connection.CreateAuthorizationUrl());
                    browser.ShowDialog();
                    if (browser.DialogResult.HasValue && browser.DialogResult.Value)
                    {
                        connection.SetAccessTokenWithPin(browser.PIN);
                        Properties.Settings.Default.AccessToken = connection.Token;
                        Properties.Settings.Default.AccessTokenSecret = connection.TokenSecret;
                        Properties.Settings.Default.Save();
                    }
                    else
                    {
                        App.Current.Shutdown();
                    }
                }
            }
            else
            {
                connection.Token = token;
                connection.TokenSecret = tokenSecret;
            }
        }

        private void StartRefresh()
        {
            //if (refreshBackgroundWorker.IsBusy)
            //{
            //    return;
            //}
            this.Dispatcher.Invoke(new Action(() =>
            {
                StatusTextBlock.Text = "Loading...";
                ConnectionProgressBar.Visibility = System.Windows.Visibility.Visible;
            }));
            //ConnectionProgressBar.Value = 0;

            //refreshBackgroundWorker.RunWorkerAsync();
        }

        private void EndRefresh()
        {
            this.Dispatcher.Invoke(new Action(() =>
                {
                    StatusTextBlock.Text = "Update Complete";
                    ConnectionProgressBar.Visibility = System.Windows.Visibility.Hidden;
                }));
        }

        private void DirectMessage(string screenName)
        {
            MainUpdateForm.TweetTextBox.Text = "D " + screenName + " ";
            FormExpander_MouseEnter(null, null);
            MainUpdateForm.TweetTextBox.Focus();
            MainUpdateForm.TweetTextBox.Select(MainUpdateForm.TweetTextBox.Text.Length, 0);
        }

        private void UserStreamSetup()
        {
            //observingSynchronizerのセットアップ
            var observer = new CachingUpdateTaskObserver(TwitterCommandFactory.CreateLocalTwitterCommand());
            var task = new TwitterPushTask<TwitterData>("stat update task");
            task.Subscribe(observer);
            App.CurrentApp.ObservingSynchronizer.AddTask(task);

            var remote = TwitterCommandFactory.CreateRemoteTwitterCommand();
            this.streamMonitor = remote.OpenUserStreams();

            //ObservingSynchronizerに通知が行くようにします。
            this.streamMonitor.Subscribe(App.CurrentApp.ObservingSynchronizer);

            //streamの読み込みを開始します。
            this.streamMonitor.StartMonitoring();
        }

        #endregion

        #region Private Events

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                StatusTextBlock.Text = "Loading User ID...";
                SetupConnection();
                StatusTextBlock.Text = "Finished Loading User ID";

                App.CurrentApp.User = new TwitterCommand(App.CurrentApp.Connection).VerifyCredentials();
                var localCommand = TwitterCommandFactory.CreateLocalTwitterCommand();
                localCommand.RefreshCurrentUser(TwitterCommandFactory.CreateRemoteTwitterCommand());
                App.CurrentApp.User = localCommand.CurrentUser;

                //ここでUserStreamを開きます
                UserStreamSetup();

                //UserにINotifyProperetyChangedが実装されるまで
                var bmp = new System.Windows.Media.Imaging.BitmapImage();
                bmp.BeginInit();
                bmp.UriSource = new Uri(App.CurrentApp.User.ProfileImageUrl);
                bmp.EndInit();
                this.MyProfileImage.Source = bmp;

                ZonePanel1.ChangeZone(ZonePanel.Types.Default);
                ZonePanel1.Refresh();
                //StartRefresh();

                //refreshTimer.Start();
                App.CurrentApp.TimerSynchronizer.TimerStarted += new EventHandler((o, args) => StartRefresh());
                App.CurrentApp.TimerSynchronizer.TimerFinished += new EventHandler((o, args) => EndRefresh());
                App.CurrentApp.TimerSynchronizer.Start((int)TweetZone.Properties.Settings.Default.RefreshInterval.TotalMilliseconds);
            }
            catch 
            {
                throw;
            }
        }

        private void refreshTimer_Tick(object sender, EventArgs e)
        {
            StartRefresh();
        }

        private void UpdateForm_UpdateCancellationPending(object sender, EventArgs e)
        {
            FormExpander.IsExpanded = false;
        }

        void MainUpdateForm_UpdateButton_Click(object sender, RoutedEventArgs e)
        {
            FormExpander.IsExpanded = false;
        }

        private void FormExpander_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            FormExpander.IsExpanded = true;
        }

        private void FormExpander_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            FormExpander.IsExpanded = false;
        }

        private void OpenSettingsButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SettingsWindow window = new SettingsWindow();
            window.ShowDialog();
            if (window.DialogResult.HasValue && window.DialogResult.Value)
            {
                StatusTextBlock.Text = "Your settings file is updated";
            }
        }

        private void FriendSearchButton_Click(object sender, RoutedEventArgs e)
        {
            (new Tools.SearchUsersByKeywordWindow()).Show();
        }

        private void ZoneComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            User user = App.CurrentApp.User;
            if (ZoneComboBox.SelectedItem == DefaultZoneItem)
            {
                ZonePanel1.ChangeZone(ZonePanel.Types.Default);
            }
            else if (ZoneComboBox.SelectedItem == AnalysisZoneItem)
            {
                ZonePanel1.ChangeZone(ZonePanel.Types.Analysis);
            }
            else if (ZoneComboBox.SelectedItem == VariousZoneItem)
            {
                ZonePanel1.ChangeZone(ZonePanel.Types.Various);
            }
            ZonePanel1.RefreshAsync();
        }

        private void ProfileMyselfSbutton_Click(object sender, RoutedEventArgs e)
        {
            var wnd = new UserProfileWindow(App.CurrentApp.User);
            wnd.Show();
        }

        #endregion

        #region Private BackgroundWorker Events

        //private void refreshBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        //{
        //    //containersがすべてcahcingを参照するまで
        //    try
        //    {
        //        if (e.Error == null)
        //        {
        //            ZonePanel1.RefreshAsync(
        //                completed: null,
        //                allCompleted: new Action(() =>
        //                {
        //                    StatusTextBlock.Text = "Update Completed";
        //                }));
        //        }
        //        else
        //        {
        //            var prov = new ErrorMessageProvider(e.Error);
        //            StatusTextBlock.Text += " Update Failed : " + prov.CreateErrorMessage();
        //        }
        //    }
        //    finally
        //    {
        //        ConnectionProgressBar.Visibility = System.Windows.Visibility.Collapsed;
        //    }
        //}

        //private void refreshBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        //{
        //    TwitterCaching caching = new TwitterCaching(TweetZone.Properties.Settings.Default.TwitterConnectionString);
        //    TwitterCommand command = new TwitterCommand(App.CurrentApp.Connection);

        //    if (!e.Cancel && !this.refreshBackgroundWorker.CancellationPending)
        //    {
        //        Timeline cachedHome = null;
        //        TimelineOption homeOption = new TimelineOption()
        //        {
        //            Count = TweetZone.Properties.Settings.Default.NumberOfStatusesToGet,
        //        };
        //        cachedHome = caching.GetHomeTimeline(homeOption);
        //        if (cachedHome.Count() > 0)
        //        {
        //            homeOption.SinceID = cachedHome.First().ID;
        //        }
        //        //TODO: 削除タイミングに問題ありか？
        //        caching.UpdateDatabase(command.GetHomeTimeline(homeOption), cachedHome, TimelineTypes.Home);
        //    }

        //    if (!e.Cancel && !this.refreshBackgroundWorker.CancellationPending)
        //    {
        //        Timeline cachedMentions = null;
        //        TimelineOption mentionsOption = new TimelineOption()
        //        {
        //            Count = TweetZone.Properties.Settings.Default.NumberOfStatusesToGet
        //        };
        //        cachedMentions = caching.GetMentionsTimeline(mentionsOption);
        //        if (cachedMentions.Count() > 0) //中途半端に消えている可能性
        //        {
        //            mentionsOption.SinceID = cachedMentions.First().ID;
        //        }
        //        caching.UpdateDatabase(command.GetMentionsTimeline(mentionsOption), cachedMentions, TimelineTypes.Mentions);
        //    }

        //    if (!e.Cancel && !this.refreshBackgroundWorker.CancellationPending)
        //    {
        //        DirectMessageOption directMessageOption = new DirectMessageOption()
        //        {
        //            Count = TweetZone.Properties.Settings.Default.NumberOfStatusesToGet
        //        };

        //        caching.UpdateDirectMessageDatabase(new List<DirectMessage>(command.GetDirectMessages(directMessageOption)), new List<DirectMessage>(caching.GetDirectMessages(directMessageOption)));
        //    }

        //}

        #endregion

        #region Private Fields

        //private DispatcherTimer refreshTimer = new DispatcherTimer();
        //private BackgroundWorker refreshBackgroundWorker = new BackgroundWorker();
        private TwitterStreamMonitor streamMonitor;

        #endregion


    }
}
